package org.example.fboot.config.jwt;

import com.alibaba.fastjson2.JSONObject;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.MalformedJwtException;
import io.micrometer.common.util.StringUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.security.web.server.context.ServerSecurityContextRepository;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Collection;

@Component
@Slf4j
public class JwtSecurityWebFilter implements ServerSecurityContextRepository {

    @Resource
    private AccessComponent accessComponent;

    @Override
    public Mono<Void> save(ServerWebExchange exchange, SecurityContext context) {
        log.info("JwtSecurityWebFilter--->save");
        return Mono.empty();
    }

    /**
     * 校验token
     *
     * @param exchange the exchange to look up the {@link SecurityContext}
     * @return
     */
    @Override
    public Mono<SecurityContext> load(ServerWebExchange exchange) {
        ServerHttpRequest request = exchange.getRequest();
        HttpHeaders headers = request.getHeaders();
        String token = headers.getFirst(HttpHeaders.AUTHORIZATION);
        String userKey = headers.getFirst("user");
        if (StringUtils.isNotBlank(token) && StringUtils.isNotBlank(userKey)) {
            try {
                Claims payload = accessComponent.getPayload(token);
                JSONObject from = JSONObject.from(payload.get(HttpHeaders.AUTHORIZATION));
                Authentication authentication = from.to(Authentication.class);
                return Mono.just(new SecurityContextImpl(authentication));
            }catch (Exception e){
                return Mono.error(e);
            }
        }
        return Mono.error(new JwtException("令牌失效"));
    }
}
